package com.sora.sora.security.login.service.impl;

import com.sora.sora.common.model.entity.AuthenticationEntity;
import com.sora.sora.common.model.vo.AuthenticationVO;
import com.sora.sora.security.UserDetail;
import com.sora.sora.security.authorise.service.ResourcesService;
import com.sora.sora.security.login.JwtManager;
import com.sora.sora.security.login.mapper.LoginMapper;
import com.sora.sora.security.login.model.param.LoginParam;
import com.sora.sora.security.login.service.LoginService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Set;
import java.util.stream.Collectors;

@Service("loginService")
public class LoginServiceImpl implements UserDetailsService, LoginService {

    @Resource
    private ResourcesService resourcesService;

    @Resource
    private LoginMapper loginMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /*
    * 懒加载，
    * 这里的 AuthenticationManager 和 SecurityConfiguration 中的 LoginService 形成循环依赖，
    * 初始化的时候springboot就不能决定先创建哪个bean
    * */
//    @Lazy
//    @Resource
//    private AuthenticationManager authenticationManager;

    @Resource
    private JwtManager jwtManager;

    @Resource
    private PasswordEncoder passwordEncoder;



    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        AuthenticationEntity entity1 = loginMapper.queryByName(s);
        AuthenticationEntity entity2 = loginMapper.queryByEmail(s);

        if (entity1 == null && entity2 == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        AuthenticationEntity entity = entity1 != null ? entity1 : entity2;

        Set<SimpleGrantedAuthority> authorities = resourcesService.getResourcesIdByUserId(entity.getId())
                .stream()
                .map(String::valueOf)
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toSet());

        return new UserDetail(entity, authorities);
    }

    @Override
    public AuthenticationVO login(LoginParam loginParam) {
//        String name = loginParam.getName();
//        String password = "";
//        Integer id = null;
//        AuthenticationEntity entity1 = loginMapper.queryByEmail(name);
//        if (entity1 != null) {
//            name = entity1.getName();
//            password = entity1.getPassword();
//            id = entity1.getId();
//        }
//
//        Authentication token = new UsernamePasswordAuthenticationToken(name, loginParam.getPassword());
//        Authentication authenticate = authenticationManager.authenticate(token);
//        SecurityContextHolder.getContext().setAuthentication(authenticate);
//
//        Integer id = loginMapper.queryIdByName(name);
//        String email = loginMapper.queryEmailByName(name);
//        return new UserVO(id, name, jwtManager.generateAccessToken(name), jwtManager.generateRefreshToken(email));


        String password = loginParam.getPassword();

        AuthenticationEntity entity1 = loginMapper.queryByName(loginParam.getName());
        if (entity1 != null && passwordEncoder.matches(password, entity1.getPassword())) {
            return new AuthenticationVO(
                    entity1.getId(), entity1.getName(), entity1.getEmail(),
                    jwtManager.generateAccessToken(entity1.getName()),
                    jwtManager.generateRefreshToken(entity1.getEmail()),
                    entity1.getAvatar(), entity1.getSign(), entity1.getGender()
            );
//            return new AuthenticationVO(entity1.getId(), entity1.getName(),
//                    jwtManager.generateAccessToken(entity1.getName()),
//                    jwtManager.generateRefreshToken(entity1.getEmail()));
        }

        AuthenticationEntity entity2 = loginMapper.queryByEmail(loginParam.getName());
        if (entity2 != null && passwordEncoder.matches(password, entity2.getPassword())) {
            return new AuthenticationVO(entity2.getId(), entity2.getName(),
                    jwtManager.generateAccessToken(entity2.getName()),
                    jwtManager.generateRefreshToken(entity2.getEmail()));
        }
        return null;
    }

    @Override
    public boolean resetPassword(String email, String password) {
        if (!Boolean.TRUE.equals(redisTemplate.hasKey(email))) {
            return false;
        }
        loginMapper.updatePasswordByEmail(passwordEncoder.encode(password), email);
        return true;
    }
}
